package controllers;


import java.util.ArrayList;
import java.util.Date;
import java.util.ResourceBundle;

import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.SessionScoped;
import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.validator.ValidatorException;
import javax.servlet.http.HttpSession;

import beans.FolderBeanRemote;
import beans.HistoryBeanRemote;
import beans.InboxBeanRemote;
import beans.ResourcesBeanRemote;
import beans.UserBeanRemote;
import dto.DTOUser;
import dto.FolderDTO;
import dto.GeneralMessageDTO;
import dto.HistoryDTO;
import dto.RepositoryDTO;
import dto.ResourceDTO;
import enums.UserOperation;

/**
 *  
 * @author tokea
 * Controler responsabil pentru operatiile legate de pagina principala a userului
 */

@ManagedBean
@SessionScoped
public class UserController {
	
	@EJB
	FolderBeanRemote folderBean;
	
	@EJB
	ResourcesBeanRemote resourceBean;
	
	@EJB
	HistoryBeanRemote historyBean;
	
	@EJB
	InboxBeanRemote inboxBean;
	
	@EJB
	UserBeanRemote userBean;
	
	@ManagedProperty(value = "#{dTOUser}")
	private DTOUser userDto;
	
	@ManagedProperty(value = "#{repositoryDTO}")
	private RepositoryDTO repDto;
	
	private int userId = 2;
	private String username;
	private String name;
	private String content;
	private boolean logged;
	private ArrayList<FolderDTO> folderz;
	private ArrayList<ResourceDTO> resourcez;
	private ArrayList<HistoryDTO> historyz;
	private boolean folderRender = false;
	private boolean resourceRender = false;
	private boolean repositoryRender = false;
	private Object selected;
	private UserOperation operation = UserOperation.DEFAULT;
	private boolean sent;
	private boolean supervisor;
	private int modifyId;
	
	
	//Getters and Setters
	
	public void setRepDto(RepositoryDTO repDto) {
		this.repDto = repDto;
	}
	
	
	public RepositoryDTO getRepDto()
	{
		return repDto;
	}


	public void setUserDto(DTOUser userDto) {
		this.userDto = userDto;
	}

	
	public String getUsername()
	{
		return username;
	}
	
	public void setUsername(String username)
	{
		this.username = username;
	}
	
	public boolean isLogged()
	{
		return logged;
	}
	
	public void setLogged(boolean logged)
	{
		this.logged = logged;
	}
	
	public ArrayList<FolderDTO> getFolderz()
	{
		if(folderz == null){
			
			int id = Integer.parseInt(repDto.getRepID());
			folderz = folderBean.getFoldersFromRepository(id);
		}
		return folderz;
	}
	
	
	public ArrayList<ResourceDTO> getResourcez()
	{
		if(resourcez == null){
			int id = Integer.parseInt(repDto.getRepID());
			resourcez = folderBean.getResourcesFromRepository(id);
		}
		return resourcez;
	}
	
	
	public boolean isFolderRender()
	{
		return folderRender;
	}

	public void setFolderRender(boolean folderRender)
	{
			this.resourceRender = !folderRender;
			this.folderRender = folderRender;
	}

	public boolean isResourceRender()
	{
		return resourceRender;
	}

	public void setResourceRender(boolean resourceRender)
	{
			this.folderRender = !resourceRender;
			this.resourceRender = resourceRender;
	}

	public Object getSelected()
	{
		return selected;
	}

	public void setSelected(Object selected)
	{
		if(modifyId != 0){
			for(ResourceDTO r:resourcez)
				if(modifyId == r.getId()){
					resourceBean.unlockResource(modifyId, userDto.getId());
					modifyId = 0;
					r.setLockerId(1);
				}
		}
		if(selected instanceof ResourceDTO){
			this.repositoryRender = false;
			this.resourceRender = true; 
			this.folderRender = false;
			System.out.println("Resource instance");
		}
		else if(selected instanceof FolderDTO){
			this.folderRender = true;	
			this.resourceRender = false;
			this.repositoryRender = false;
			System.out.println("Folder instance");
		}else {
			this.folderRender = false;	
			this.resourceRender = false;
			this.repositoryRender = true;
			System.out.println("Repository instance");
		}
		this.operation = UserOperation.DEFAULT;
		this.name = "";
		this.content = "";
		this.selected = selected;
		this.sent = false;
	}

	
	
	public UserOperation getOperation()
	{
		return operation;
	}

	public void setOperation(UserOperation operation)
	{
		if(modifyId != 0){
			for(ResourceDTO r:resourcez)
				if(modifyId == r.getId()){
					resourceBean.unlockResource(modifyId, userDto.getId());
					r.setLockerId(1);
					modifyId = 0;
				}
		}
		this.sent = false;
		this.operation = operation;
	}

	
	public String getName()
	{
		return name;
	}

	public void setName(String name)
	{
		this.name = name;
	}

	public String getContent()
	{
		if(selected instanceof ResourceDTO){
			return ((ResourceDTO) selected).getContent();
		}else
			return content;
	}

	public void setContent(String content)
	{
		if(selected instanceof ResourceDTO)
			((ResourceDTO) selected).setContent(content);
		this.content = content;
	}

	public int getUserId()
	{
		return userId;
	}

	public void setUserId(int userId)
	{
		this.userId = userId;
	}
	
	
	
	
	public ArrayList<HistoryDTO> getHistoryz(){
		return historyz;
	}

  
	public boolean isNotEmptyHistory()
	{
		return historyz.size() != 0;
	}

	
	

	public boolean isRepositoryRender()
	{
		return repositoryRender;
	}


	public void setRepositoryRender(boolean repositoryRender)
	{
		this.repositoryRender = repositoryRender;
	}


	public boolean isSent()
	{
		return sent;
	}

	
	public boolean isSupervisor()
	{	
		if(!this.supervisor){
			this.supervisor = userBean.isSupervisor(userDto.getId(), Integer.parseInt(repDto.getRepID()));
			if(!this.supervisor && userDto.getId() == 2)
				this.supervisor = true;
		}
		return supervisor;
	}


	public void setSupervisor(boolean supervisor)
	{
		this.supervisor = supervisor;
	}
	
	//Methods
	public String editContent(){
		if(selected instanceof ResourceDTO)
			if(!this.operation.equals(UserOperation.MODIFY)){
				this.operation = UserOperation.MODIFY;
				((ResourceDTO) selected).setLockerId(userId);
				resourceBean.lockResource(((ResourceDTO) selected).getId(), userDto.getId());
				modifyId = ((ResourceDTO) selected).getId();
			}
			else
				this.operation = UserOperation.DEFAULT;
		return null;
	}
	
	public String createResource(){
		if(!this.operation.equals(UserOperation.CREATE_RES))
			this.operation = UserOperation.CREATE_RES;
		else
			this.operation = UserOperation.DEFAULT;
		return null;
	}
	
	public String submitResource(){
		if(selected instanceof FolderDTO){
			ResourceDTO newRes = new ResourceDTO();
			newRes.setContent(content);
			newRes.setName(name);
			newRes.setFolderId(((FolderDTO) selected).getId());
			newRes = resourceBean.createResource(newRes,userDto.getId());
			resourcez.add(newRes);
			name = "";
			content = "";
			modifyId = 0;
			this.operation = UserOperation.DEFAULT;
		}
		return null;
	}
	
	public String createFolder(){
		if(!this.operation.equals(UserOperation.CREATE_FOL))
			this.operation = UserOperation.CREATE_FOL;
		else
			this.operation = UserOperation.DEFAULT;
		return null;
	}
	
	
	public String submitFolder(){
		int parentId = 0;
		if(selected instanceof FolderDTO){
			parentId = ((FolderDTO) selected).getId();
		}else if(selected instanceof RepositoryDTO){
			parentId = Integer.parseInt(((RepositoryDTO) selected).getRepID());
		}
		FolderDTO newFol = new FolderDTO();
		newFol.setName(name);
		newFol.setId_parent(parentId);
		newFol = folderBean.createFolder(newFol);
		folderz.add(newFol);
		name = "";
		this.operation = UserOperation.DEFAULT;
		return null;
	}
	
	public String cancel(){
		this.name = null;
		this.content = null;
		this.operation = UserOperation.DEFAULT;
		this.sent = false;
		return null;
	}
	
	public String submitNewContent(){
		// /// internationalizare
				HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
						.getExternalContext().getSession(true);
				LocaleController language = (LocaleController) session
						.getAttribute("language");
				String messageBundleName = "errorMessages.errors";
				if (language.getLanguage() == "ro") {
					messageBundleName += "_ro";
				} else if (language.getLanguage() == "hu") {
					messageBundleName += "_hu";
				} else if (language.getLanguage() == "de") {
					messageBundleName += "_de";
				}
				ResourceBundle messageBundle = ResourceBundle
						.getBundle(messageBundleName);
				// ///
		if(selected instanceof ResourceDTO){
			if(resourceBean.verifyLock(((ResourceDTO) selected).getId(),userDto.getId())){
				this.operation = UserOperation.DEFAULT;
				FacesMessage msg = new FacesMessage(messageBundle.getString("resIL"));
				throw new ValidatorException(msg);
			}else{
				resourceBean.modifyResourceContent((ResourceDTO)selected,userDto.getId());
				for(ResourceDTO r:resourcez){
					if(modifyId == r.getId()){
						r.setLockerId(1);
					}
				}
				modifyId = 0;
				this.operation = UserOperation.DEFAULT;
			}
		}
		return null;
	}
	
	public String viewHistory(){
		if(!this.operation.equals(UserOperation.HISTORY)){
			if(selected instanceof ResourceDTO){
				historyz = new ArrayList<HistoryDTO>(historyBean.allHistoryToSource(((ResourceDTO) selected).getId()));
				this.operation = UserOperation.HISTORY;
			}else
				this.operation = UserOperation.DEFAULT;
		}else
			this.operation = UserOperation.DEFAULT;
		return null;
	}
	
	
	public String refreshRepository(){
		this.folderz = null;
		this.resourcez = null;
		return null;
	}
	
	public String sendUnlockRequest(){
		if(selected instanceof ResourceDTO){
			int idRep = Integer.parseInt(repDto.getRepID());
			GeneralMessageDTO mDto = new GeneralMessageDTO(((ResourceDTO) selected).getId()+"", userDto.getId(), "unlock_resource", new Date(), idRep);
			this.sent = inboxBean.addGeneralMessage(mDto);
		}
		return null;
	}
	
	public String sendDeleteRequest(){
		if(selected instanceof ResourceDTO){
			int idRep = Integer.parseInt(repDto.getRepID());
			GeneralMessageDTO mDto = new GeneralMessageDTO(((ResourceDTO) selected).getId()+"", userDto.getId(), "delete_resource", new Date(), idRep);
			this.sent = inboxBean.addGeneralMessage(mDto);
		}
		return null;
	}
	
	
	public String deleteResource(){
		if(selected instanceof ResourceDTO){
			
			resourceBean.deleteResource(((ResourceDTO) selected).getId(),userDto.getId());
			for(ResourceDTO r:resourcez)
				if(r.getId() == ((ResourceDTO)selected).getId())
					resourcez.remove(r);
			this.operation = UserOperation.DEFAULT;
		}
		return null;
	}
	
	public String unlockResource(){
		if(selected instanceof ResourceDTO){
			
			resourceBean.unlockResource(((ResourceDTO) selected).getId(), userDto.getId());
			for(ResourceDTO r:resourcez)
				if(r.getId() == ((ResourceDTO)selected).getId())
					r.setLockerId(1);
			this.operation = UserOperation.DEFAULT;
		}
		return null;
	}
	
	//Validators
	
	
	


	/**
	 * @author tokea
	 * @param fc
	 * @param c
	 * @param value
	 */
	public void validateFolderName(FacesContext fc, UIComponent c, Object value){
		// /// internationalizare
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
				.getExternalContext().getSession(true);
		LocaleController language = (LocaleController) session
				.getAttribute("language");
		String messageBundleName = "errorMessages.errors";
		if (language.getLanguage() == "ro") {
			messageBundleName += "_ro";
		} else if (language.getLanguage() == "hu") {
			messageBundleName += "_hu";
		} else if (language.getLanguage() == "de") {
			messageBundleName += "_de";
		}
		ResourceBundle messageBundle = ResourceBundle
				.getBundle(messageBundleName);
		// ///
		String name = (String)value;
		int id = 0;
		if(selected instanceof FolderDTO){
			id = ((FolderDTO) selected).getId();
		}else if(selected instanceof RepositoryDTO){
			id = Integer.parseInt(((RepositoryDTO) selected).getRepID());
		}
		
		
		if( name != null && !name.equals("")){
			
			if(!name.matches("^[A-Za-z0-9_-]{3,15}$")){
				FacesMessage msg = new FacesMessage(messageBundle.getString("nameNotContainSpecChr"));
				throw new ValidatorException(msg);
			}else if(!folderBean.verifyUniqueness(id, name)){
				FacesMessage msg = new FacesMessage(messageBundle.getString("nameTakenInFolder"));
				throw new ValidatorException(msg);
			}
			
		}
	}
	
	
	/**
	 * @author tokea
	 * @param fc
	 * @param c
	 * @param value
	 */
	public void validateResourceName(FacesContext fc, UIComponent c, Object value){
		// /// internationalizare
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
				.getExternalContext().getSession(true);
		LocaleController language = (LocaleController) session
				.getAttribute("language");
		String messageBundleName = "errorMessages.errors";
		if (language.getLanguage() == "ro") {
			messageBundleName += "_ro";
		} else if (language.getLanguage() == "hu") {
			messageBundleName += "_hu";
		} else if (language.getLanguage() == "de") {
			messageBundleName += "_de";
		}
		ResourceBundle messageBundle = ResourceBundle
				.getBundle(messageBundleName);
		// ///
		String name = (String)value;
		
		if(selected instanceof FolderDTO && name != null && !name.equals("")){
			
			if(!name.matches("^[A-Za-z0-9_-]{3,15}$")){
				FacesMessage msg = new FacesMessage(messageBundle.getString("nameNotContainSpecChr"));
				throw new ValidatorException(msg);
			}else if(!resourceBean.verifyUniqueness(((FolderDTO) selected).getId(), name)){
				FacesMessage msg = new FacesMessage(messageBundle.getString("nameTakenInFolder"));
				throw new ValidatorException(msg);
			}
		}
	}
	
	
	
	
	/**
	 * @author tokea
	 * @param fc
	 * @param c
	 * @param value
	 */
	public void validateContentArea(FacesContext fc, UIComponent c, Object value){
		// /// internationalizare
		HttpSession session = (HttpSession) FacesContext.getCurrentInstance()
				.getExternalContext().getSession(true);
		LocaleController language = (LocaleController) session
				.getAttribute("language");
		String messageBundleName = "errorMessages.errors";
		if (language.getLanguage() == "ro") {
			messageBundleName += "_ro";
		} else if (language.getLanguage() == "hu") {
			messageBundleName += "_hu";
		} else if (language.getLanguage() == "de") {
			messageBundleName += "_de";
		}
		ResourceBundle messageBundle = ResourceBundle
				.getBundle(messageBundleName);
		// ///
		String content = (String)value;
		
		if(content != null && !content.equals("") && content.contains("<script")){
			FacesMessage msg = new FacesMessage(messageBundle.getString("niceTry"));
			throw new ValidatorException(msg);
		}
		
		if((selected instanceof ResourceDTO)){
			
			if(resourceBean.verifyLock(((ResourceDTO) selected).getId(),userDto.getId())){
				FacesMessage msg = new FacesMessage(messageBundle.getString("resLocked"));
				throw new ValidatorException(msg);
			}else if(resourceBean.verifyLockedByUser(((ResourceDTO) selected).getId(),userDto.getId())){
				System.out.println(resourceBean.verifyLockedByUser(((ResourceDTO) selected).getId(),userDto.getId()));
				FacesMessage msg = new FacesMessage(messageBundle.getString("resWU"));
				throw new ValidatorException(msg);
			}
		}
	}
	
}
